// glm.h
#pragma once

#include <array>
#include <stdexcept>
#include <iostream>
#include "geometry.h"

namespace glm 
{
	#define M_PI       3.14159265358979323846   // pi

	template <size_t N>
	class mat 
	{
		std::array<std::array<float, N>, N> matrix;
	public:
		// 默认构造函数，初始化为单位矩阵
		mat() 
		{
			for (size_t i = 0; i < N; ++i) 
			{
				for (size_t j = 0; j < N; ++j) 
				{
					matrix[i][j] = (i == j) ? 1.0f : 0.0f;
				}
			}
		}

		static mat<N> identity() 
		{
			return mat<N>{};
		}

		// 访问运算符
		std::array<float, N>& operator[](size_t row) 
		{
			if (row >= N) throw std::out_of_range("Row index out of range");
			return matrix[row];
		}

		const std::array<float, N>& operator[](size_t row) const 
		{
			if (row >= N) throw std::out_of_range("Row index out of range");
			return matrix[row];
		}

		// 矩阵乘法
		mat<N> operator*(const mat<N>& other) const 
		{
			mat<N> result;
			for (size_t i = 0; i < N; ++i) 
			{
				for (size_t j = 0; j < N; ++j) 
				{
					result[i][j] = 0.0f;
					for (size_t k = 0; k < N; ++k) 
					{
						result[i][j] += matrix[i][k] * other.matrix[k][j];
					}
				}
			}
			return result;
		}

		// 转置
		mat<N> transpose() const 
		{
			mat<N> result;
			for (size_t i = 0; i < N; ++i) 
			{
				for (size_t j = 0; j < N; ++j) 
				{
					result[j][i] = matrix[i][j];
				}
			}
			return result;
		}

		// 行列式计算（递归实现）
		float determinant() const 
		{
			if constexpr (N == 1) 
			{
				return matrix[0][0];
			}
			else 
			{
				float det = 0.0f;
				for (size_t i = 0; i < N; ++i) 
				{
					det += matrix[0][i] * cofactor(0, i);
				}
				return det;
			}
		}

		// 逆矩阵
		mat<N> inverse() const 
		{
			float det = determinant();
			if (det == 0.0f) throw std::runtime_error("Singular matrix");

			mat<N> adjugate;
			for (size_t i = 0; i < N; ++i) 
			{
				for (size_t j = 0; j < N; ++j) 
				{
					adjugate[j][i] = cofactor(i, j); // 直接存储转置（伴随矩阵）
				}
			}

			// 除以行列式
			for (size_t i = 0; i < N; ++i) 
			{
				for (size_t j = 0; j < N; ++j) 
				{
					adjugate[i][j] /= det;
				}
			}
			return adjugate;
		}

		// 余子式计算
		float cofactor(size_t row, size_t col) const
		{
			if constexpr (N == 1) 
			{
				return 1.0f; // 1x1 矩阵的余子式为1
			}
			else {
				mat<N - 1> submatrix;
				size_t sub_i = 0;
				for (size_t i = 0; i < N; ++i) 
				{
					if (i == row) continue;
					size_t sub_j = 0;
					for (size_t j = 0; j < N; ++j) 
					{
						if (j == col) continue;
						submatrix[sub_i][sub_j] = matrix[i][j];
						++sub_j;
					}
					++sub_i;
				}
				float sign = ((row + col) % 2 == 0) ? 1.0f : -1.0f;
				return sign * submatrix.determinant();
			}
		}

		// 输出友元函数
		friend std::ostream& operator<<(std::ostream& os, const mat<N>& m) 
		{
			for (size_t i = 0; i < N; ++i) 
			{
				for (size_t j = 0; j < N; ++j) 
				{
					os << m.matrix[i][j] << "\t";
				}
				os << "\n";
			}
			return os;
		}

		// 转换为低维矩阵（例如 mat4 → mat3）
		template <size_t M>
		mat<M> to_mat() const 
		{
			static_assert(M <= N, "Target dimension must be smaller");
			mat<M> result;
			for (size_t i = 0; i < M; ++i) 
			{
				for (size_t j = 0; j < M; ++j) 
				{
					result[i][j] = matrix[i][j];
				}
			}
			return result;
		}

		mat<3> to_mat3() const 
		{
			static_assert(N >= 3, "Source matrix must be at least 3x3");
			return to_mat<3>(); 
		}
	};

	// 常用类型别名
	using mat3 = mat<3>;
	using mat4 = mat<4>;

	Vec4f operator*(const mat4& m, const Vec4f& v);
	Vec3f operator*(const mat3& m, const Vec3f& v);
	mat3 Vec3toMat3(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3);

	// 角度->弧度
	float radians(float degrees);
	// 平移矩阵
	mat4 translate(const mat4& matrix, const Vec3f& v);
	// 缩放矩阵
    mat4 scale(const mat4& matrix, const Vec3f& v);
    // 旋转矩阵
    mat4 rotate(const mat4& matrix, float angle, const Vec3f& axis);
	// Look At 矩阵
    mat4 lookAt(const Vec3f& eye, const Vec3f& center, const Vec3f& up);
	// 正交投影矩阵
	mat4 ortho(float left, float right, float bottom, float top, float n, float f);
	// 透视投影矩阵
	mat4 perspective(float fov, float aspect, float n, float f);
	// 视口矩阵
    mat4 viewport(float w, float h);
	// 求重心坐标--未经过透视矫正
	Vec3f barycentric(const Vec3f& A, const Vec3f& B, const Vec3f& C, const Vec3f& P);
	// 求重心坐标--经过透视矫正（二维插值但 z 分量存储 w）
	Vec3f barycentricCorrect(const Vec3f& A, const Vec3f& B, const Vec3f& C, const Vec3f& P);
	// 求三角面的切线
    Vec3f tangent(std::pair<Vec3f, Vec2f> p1, std::pair<Vec3f, Vec2f> p2, std::pair<Vec3f, Vec2f> p3);
	// 反射
	Vec3f reflect(const Vec3f& I, const Vec3f& N);
} // namespace glm